package com.jingdianjichi.controller;

import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import com.jingdianjichi.enums.CallBackTypeEnum;
import com.jingdianjichi.handler.CallBackTypeHandler;
import com.jingdianjichi.handler.CallBackTypeHandlerFactory;
import com.jingdianjichi.util.WxUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.Map;

/**
 * 微信服务器配置校验接口
 * URL: https://<你的域名>/wx
 * Token: 与微信后台填写的完全一致（此处为 mytoken123）
 */
@RestController
@RequestMapping("/wx")
public class WxCallbackController {

    private static final Logger logger = LoggerFactory.getLogger(WxCallbackController.class);

    private static final String TOKEN = "mytoken123";
    
    @Resource
    private CallBackTypeHandlerFactory callBackTypeHandlerFactory;

    /**
     * 微信在“提交”服务器配置时，会以GET方式请求该接口
     * 含有四个参数：signature、timestamp、nonce、echostr
     * 校验成功需要原样返回 echostr 文本
     */
    @GetMapping(produces = "text/plain;charset=UTF-8")
    public ResponseEntity<String> verify(@RequestParam(name = "signature", required = false) String signature,
                                         @RequestParam(name = "timestamp", required = false) String timestamp,
                                         @RequestParam(name = "nonce", required = false) String nonce,
                                         @RequestParam(name = "echostr", required = false) String echostr) {
        if (StrUtil.hasBlank(signature, timestamp, nonce, echostr)) {
            logger.warn("[WX VERIFY] missing param, signature={}, timestamp={}, nonce={}, echostr={}", signature, timestamp, nonce, echostr);
            return new ResponseEntity<>("bad request", HttpStatus.BAD_REQUEST);
        }
        // 1. 将 token、timestamp、nonce 三个参数进行字典序排序
        String[] arr = {TOKEN, timestamp, nonce};
        Arrays.sort(arr);
        String sorted = arr[0] + "," + arr[1] + "," + arr[2];
        // 2. 拼接并进行 SHA1 加密
        String toSign = arr[0] + arr[1] + arr[2];
        String sign = SecureUtil.sha1(toSign);
        logger.info("[WX VERIFY] incoming: signature={}, timestamp={}, nonce={}, echostr={}", signature, timestamp, nonce, echostr);
        logger.debug("[WX VERIFY] token/timestamp/nonce(sorted)={}, toSign={}, sha1(sign)={}", sorted, toSign, sign);
        // 3. 与请求携带的 signature 对比，相等则返回 echostr
        if (sign.equalsIgnoreCase(signature)) {
            logger.info("[WX VERIFY] verify ok, echo back echostr");
            return ResponseEntity.ok(echostr);
        }
        logger.warn("[WX VERIFY] verify failed, calcSign={}, reqSignature={}", sign, signature);
        return new ResponseEntity<>("forbidden", HttpStatus.FORBIDDEN);
    }


    
    /**
     * 接收微信消息回调
     * @param signature 微信加密签名
     * @param timestamp 时间戳
     * @param nonce 随机数
     * @param xmlData 微信推送的XML数据
     * @return 回复消息的XML或空字符串
     */
    @PostMapping
    public String receiveMessage(@RequestParam("signature") String signature,
                               @RequestParam("timestamp") String timestamp,
                               @RequestParam("nonce") String nonce,
                               @RequestBody String xmlData) {
        try {
            logger.info("接收到微信消息回调，signature: {}, timestamp: {}, nonce: {}", signature, timestamp, nonce);
            logger.info("接收到的XML数据: {}", xmlData);
            
            // 验证签名
            if (!verifySignature(signature, timestamp, nonce)) {
                logger.warn("签名验证失败");
                return "";
            }
            
            // 解析XML消息
            Map<String, String> messageMap = WxUtil.parseWeChatXml(xmlData);
            if (messageMap == null || messageMap.isEmpty()) {
                logger.warn("XML解析失败或为空");
                return "";
            }
            
            String msgType = messageMap.get("MsgType");
            String event = messageMap.get("Event");
            String content = messageMap.get("Content");
            
            logger.info("消息类型: {}, 事件类型: {}, 消息内容: {}", msgType, event, content);
            
            // 根据消息类型和内容确定处理策略
            CallBackTypeEnum callBackType = determineCallBackType(msgType, event, content);
            if (callBackType == null) {
                logger.info("未匹配到处理策略，不回复");
                return "";
            }
            
            // 获取对应的处理器
            CallBackTypeHandler handler = callBackTypeHandlerFactory.getHandler(callBackType);
            if (handler == null) {
                logger.warn("未找到对应的处理器: {}", callBackType);
                return "";
            }
            
            // 处理消息并返回回复
            String replyXml = handler.handle(messageMap);
            logger.info("回复消息: {}", replyXml);
            
            return replyXml;
            
        } catch (Exception e) {
            logger.error("处理微信消息回调异常", e);
            return "";
        }
    }
    
    /**
     * 根据消息类型、事件类型和内容确定回调处理类型
     * @param msgType 消息类型
     * @param event 事件类型
     * @param content 消息内容
     * @return 回调处理类型枚举
     */
    private CallBackTypeEnum determineCallBackType(String msgType, String event, String content) {
        // 处理事件类型消息
        if ("event".equals(msgType)) {
            if ("subscribe".equals(event)) {
                return CallBackTypeEnum.SUBSCRIBE;
            }
            // 可以在这里添加其他事件类型的处理
        }
        
        // 处理文本消息
        if ("text".equals(msgType)) {
            if ("验证码".equals(content)) {
                return CallBackTypeEnum.POSTCAPTCHA;
            }
            // 可以在这里添加其他文本消息的处理
        }
        
        // 其他消息类型暂不处理
        return null;
    }
    
    /**
     * 验证微信签名
     * @param signature 微信签名
     * @param timestamp 时间戳
     * @param nonce 随机数
     * @return 验证结果
     */
    private boolean verifySignature(String signature, String timestamp, String nonce) {
        String[] arr = {TOKEN, timestamp, nonce};
        Arrays.sort(arr);
        String toSign = arr[0] + arr[1] + arr[2];
        String sign = SecureUtil.sha1(toSign);
        return sign.equalsIgnoreCase(signature);
    }
}